﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Big2.CardsLib;

namespace Big2.Big2Game
{
    [Serializable]
    public class Play
    {
        public List<Card> CardsList { get; set; }
        public PlayType ThePlayType { get; set; }
        public string PlayerName { get; set; }
        public bool IsLastCard { get; set; }

        public Play(List<Card> CardsSelected, string name, bool lastCard)
        {
            CardsList = CardsSelected;
            ThePlayType = GetPlayType(CardsList);
            PlayerName = name;
            IsLastCard = lastCard;
        }//Play Constructor of 3 parameter


        public static bool IsValidPlay(List<Card> cards)
        {
            try { Play.GetPlayType(cards); return true; }
            catch { return false; }
        }
        public static PlayType GetPlayType(List<Card> cards)
        {
            //change value
            CardHelper.ChangeValue(cards, true);
            int tell = 0;

            if (cards.Count() == 1)
            {
                CardHelper.ChangeValue(cards, false);
                return PlayType.Single;
            }
            else if (cards.Count() == 2)
            {
                CardHelper.ChangeValue(cards, false);
                return PlayType.Pair;
            }
            else if (cards.Count() == 3)
            {
                //if all 3 are the same value
                if (cards.ElementAt(0).isSameValue(cards.ElementAt(1)) &&
                    cards.ElementAt(0).isSameValue(cards.ElementAt(2)))
                {
                    CardHelper.ChangeValue(cards, false);
                    return PlayType.ThreeOfAKind;
                }
            }
            if (cards.Count() == 5)
            {
                //if first 3 cards and last 2 cards same
                if (IsThree(cards.ElementAt(0), cards.ElementAt(1), cards.ElementAt(2)) &&
                    IsPair(cards.ElementAt(3), cards.ElementAt(4)) ||
                    IsPair(cards.ElementAt(0), cards.ElementAt(1)) &&
                    IsThree(cards.ElementAt(2), cards.ElementAt(3), cards.ElementAt(4)))
                {
                    CardHelper.ChangeValue(cards, false);
                    return PlayType.FullHouse;
                }
            }
            if (cards.Count() == 5)
            {
                if (IsFour(cards.ElementAt(0), cards.ElementAt(1), cards.ElementAt(2), cards.ElementAt(3)) ||
                    IsFour(cards.ElementAt(1), cards.ElementAt(2), cards.ElementAt(3), cards.ElementAt(4)))
                {
                    CardHelper.ChangeValue(cards, false);
                    return PlayType.FourOfAKind;
                }
            }
            if (cards.Count() == 5)
            {
                //if all 5 cards are the same suit
                if (cards.ElementAt(0).Suit == cards.ElementAt(1).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(2).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(3).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(4).Suit)
                {
                    int match = cards.ElementAt(0).Value;

                    for (int i = 1; i < 5; i++)
                    {
                        ++match;
                        if (cards.ElementAt(i).Value != match)
                            tell = 2;
                    }
                    if (tell != 2)
                    {
                        CardHelper.ChangeValue(cards, false);
                        return PlayType.StraightFlush;
                    }
                }
            }
            if (cards.Count() == 5)
            {
                //if all 5 cards are the same suit
                if (cards.ElementAt(0).Suit == cards.ElementAt(1).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(2).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(3).Suit &&
                    cards.ElementAt(0).Suit == cards.ElementAt(4).Suit)
                {
                    CardHelper.ChangeValue(cards, false);
                    return PlayType.Flush;
                }
            }
            if (cards.Count() == 5)
            {
                int match = cards.ElementAt(0).Value;
                if (match == 3)
                {
                    CardHelper.ChangeValue(cards, false);
                    cards = CardHelper.TempSortCards(cards, true);
                    match = cards.ElementAt(0).Value;
                }
                for (int i = 1; i < 5; i++)
                {
                    ++match;
                    if (cards.ElementAt(i).Value != match)
                        tell = 1;
                }
                if (tell != 1)
                {
                    CardHelper.ChangeValue(cards, false);
                    return PlayType.Straight;
                }
            }

            CardHelper.ChangeValue(cards, false);
            throw new Exception("Invalid play type."); ;
        }//IsValidPlay()

        /*
        public bool IsValidPlay(Play hand)
        {
            switch (hand.ThePlayType)
            {
                case PlayType.Single:
                    if(CardsList.Count() == 1)
                        return true;
                    break;

                case PlayType.Pair:
                    if (CardsList.Count() == 2)
                    {
                        //if first and second card are the same value
                        if(CardsList.ElementAt(0).isSameValue(CardsList.ElementAt(1)))
                            return true;
                    }
                    break;

                case PlayType.Straight:
                    if (CardsList.Count() == 5)
                    {
                        int match = CardsList.ElementAt(0).Value;

                        for (int i = 1; i < 5; i++)
                        {
                            ++match;
                            if (CardsList.ElementAt(i).Value != match)
                                return false;
                        }
                        return true;
                    }
                    break;

                case PlayType.Flush:
                    if (CardsList.Count() == 5)
                    {
                        //if all 5 cards are the same suit
                        if (CardsList.ElementAt(0).Suit == CardsList.ElementAt(1).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(2).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(3).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(4).Suit)
                            return true;
                    }
                    break;
                    
                case PlayType.ThreeOfAKind:
                    if (CardsList.Count() == 3)
                    {
                        //if all 3 are the same value
                        if (CardsList.ElementAt(0).isSameValue(CardsList.ElementAt(1)) &&
                            CardsList.ElementAt(0).isSameValue(CardsList.ElementAt(2)))
                            return true;
                    }
                    break;

                case PlayType.FullHouse:
                    if (CardsList.Count() == 5)
                    {
                        //if first 3 cards and last 2 cards same
                        if (IsThree(CardsList.ElementAt(0), CardsList.ElementAt(1), CardsList.ElementAt(2)) &&
                            IsPair(CardsList.ElementAt(3), CardsList.ElementAt(4))                          ||
                            IsPair(CardsList.ElementAt(0), CardsList.ElementAt(1)) &&
                            IsThree(CardsList.ElementAt(2), CardsList.ElementAt(3), CardsList.ElementAt(4)))
                            return true;
                    }
                    break;

                case PlayType.FourOfAKind:
                    if (CardsList.Count() == 5)
                    {
                        if (IsFour(CardsList.ElementAt(0), CardsList.ElementAt(1), CardsList.ElementAt(2), CardsList.ElementAt(3)) ||
                            IsFour(CardsList.ElementAt(1), CardsList.ElementAt(2), CardsList.ElementAt(3), CardsList.ElementAt(4)))
                            return true;
                    }
                    break;

                case PlayType.StraightFlush:
                    if (CardsList.Count() == 5)
                    {
                        //if all 5 cards are the same suit
                        if (CardsList.ElementAt(0).Suit == CardsList.ElementAt(1).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(2).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(3).Suit &&
                            CardsList.ElementAt(0).Suit == CardsList.ElementAt(4).Suit)
                        {
                            int match = CardsList.ElementAt(0).Value;

                            for (int i = 1; i < 5; i++)
                            {
                                ++match;
                                if (CardsList.ElementAt(i).Value != match)
                                    return false;
                            }
                            return true;
                        }
                    }
                    break;
            }//switch

            return false;
        }//IsValidPlay(PlayType hand)
        */

        //compare hand to see which one is bigger
        //return 1 if left
        //return -1 if right
        //if equal compare suits
        public int ComparePlay(Play hand)
        {
            //change value
            CardHelper.ChangeValue(this.CardsList, true);
            CardHelper.ChangeValue(hand.CardsList, true);

            //assumes the hand is valid already
            //compares to see which hands wins

            //comparing single , pair and 3 of a kind is similar -- compares only first value
            if (hand.ThePlayType == PlayType.Single || hand.ThePlayType == PlayType.Pair ||
                hand.ThePlayType == PlayType.ThreeOfAKind)
            {
                if (this.CardsList.ElementAt(0).Value > hand.CardsList.ElementAt(0).Value)
                    return returnResult(this.CardsList, hand.CardsList, 1);
                else if (this.CardsList.ElementAt(0).Value < hand.CardsList.ElementAt(0).Value)
                    return returnResult(this.CardsList, hand.CardsList, -1);
                else if (this.CardsList.ElementAt(0).Value == hand.CardsList.ElementAt(0).Value)
                {
                    if (this.CardsList.ElementAt(0).Suit > hand.CardsList.ElementAt(0).Suit)
                        return returnResult(this.CardsList, hand.CardsList, 1);
                    else
                        return returnResult(this.CardsList, hand.CardsList, -1);
                }//compare suits
            }//if is single, pair or three of kind
                
            //comparing full house and 4 of a kind -- comparing middle card
            else if (hand.ThePlayType == PlayType.FullHouse)
            {
                //compares the 3 card because it can be 2-3 or 3-2
                //or 4 of a kind 1-4 or 4-1

                if (this.CardsList.ElementAt(2).Value > hand.CardsList.ElementAt(2).Value)
                    return returnResult(this.CardsList, hand.CardsList, 1);
                else if (this.CardsList.ElementAt(2).Value < hand.CardsList.ElementAt(2).Value)
                    return returnResult(this.CardsList, hand.CardsList, -1);
            }//if is full house

            //comparing straight -- compares last card
            else if (hand.ThePlayType == PlayType.Straight)
            {
                if (this.CardsList.ElementAt(4).Value > hand.CardsList.ElementAt(4).Value)
                    return returnResult(this.CardsList, hand.CardsList, 1);
                else if (this.CardsList.ElementAt(4).Value < hand.CardsList.ElementAt(4).Value)
                    return returnResult(this.CardsList, hand.CardsList, -1);
                else if (this.CardsList.ElementAt(4).Value == hand.CardsList.ElementAt(4).Value)
                {
                    if (this.CardsList.ElementAt(0).Suit > hand.CardsList.ElementAt(0).Suit)
                        return returnResult(this.CardsList, hand.CardsList, 1);
                    else
                        return returnResult(this.CardsList, hand.CardsList, -1);
                }//compare suits
            }//if is straight

            //comparing flush
            else if (hand.ThePlayType == PlayType.Flush)
            {
                if (this.CardsList.ElementAt(0).Suit > hand.CardsList.ElementAt(0).Suit)
                    return returnResult(this.CardsList, hand.CardsList, 1);
                else if (this.CardsList.ElementAt(0).Suit < hand.CardsList.ElementAt(0).Suit)
                    return returnResult(this.CardsList, hand.CardsList, -1);
                if (this.CardsList.ElementAt(0).Suit == hand.CardsList.ElementAt(0).Suit)
                {
                    if (this.CardsList.ElementAt(4).Value > hand.CardsList.ElementAt(4).Value)
                        return returnResult(this.CardsList, hand.CardsList, 1);
                    else
                        return returnResult(this.CardsList, hand.CardsList, -1);
                }//compare last value
            }//if flush

            //comparing straight flush
            else if (hand.ThePlayType == PlayType.StraightFlush)
            {
                if ((this.CardsList.ElementAt(4).Value > hand.CardsList.ElementAt(4).Value) ||
                    (this.CardsList.ElementAt(4).Suit > hand.CardsList.ElementAt(4).Suit))
                    return returnResult(this.CardsList, hand.CardsList, 1);
                else if ((this.CardsList.ElementAt(4).Value < hand.CardsList.ElementAt(4).Value) ||
                    (this.CardsList.ElementAt(4).Suit < hand.CardsList.ElementAt(4).Suit))
                    return returnResult(this.CardsList, hand.CardsList, -1);
            }//if straight flush

            throw new System.Exception("Invalid comparison of 2 hands");
        }//CompareHand(PlayType hand)

        //method to able to change value of ace and 2 to original value and
        //able to return without resulting in more code
        private int returnResult(List<Card> first, List<Card> second, int r)
        {
            //change value back
            CardHelper.ChangeValue(first, false);
            CardHelper.ChangeValue(second, false);
            return r;
        }//int returnResult(int r)

        private static bool IsPair(Card a, Card b)
        {
            return (a.isSameValue(b));

        }//bool IsPair(Card a, Card b)

        private static bool IsThree(Card a, Card b, Card c)
        {
            return (a.isSameValue(b) && a.isSameValue(c));
        }//bool IsThree(Card a, Card b, Card c)

        private static bool IsFour(Card a, Card b, Card c, Card d)
        {
            return (a.isSameValue(b) && a.isSameValue(c) && a.isSameValue(d));
        }//bool IsFour(Card a, Card b, Card c)

    }
}
